package com.honry.common.port.adapter.persistence.hibernate;

import java.util.List;

import org.hibernate.Query;

import com.honry.common.domain.model.DomainEvent;
import com.honry.common.event.EventSerializer;
import com.honry.common.event.EventStore;
import com.honry.common.event.StoredEvent;
import com.honry.common.infrastructure.persistence.PersistenceManagerProvider;

public class HibernateEventStore extends AbstractHibernateSession implements EventStore {

	public HibernateEventStore() {
		super();
	}
	public HibernateEventStore(PersistenceManagerProvider persistenceManagerProvider) {
		this();

        if (!persistenceManagerProvider.hasHibernateSession()) {
            throw new IllegalArgumentException("PersistenceManagerProvider必须具有 Hibernate Session.");
        }

        this.setSession(persistenceManagerProvider.hibernateSession());
	}
	/* 所有StoredEventId之间的StoredEvent
	 * 
	 */
	@Override
	public List<StoredEvent> allStoredEventsBetween(long aLowStoredEventId, long aHighStoredEventId) {
		Query query =
                this.session().createQuery(
                        "from StoredEvent as _obj_ "
                        + "where _obj_.eventId between ? and ? "
                        + "order by _obj_.eventId");

        query.setParameter(0, aLowStoredEventId);
        query.setParameter(1, aHighStoredEventId);

        List<StoredEvent> storedEvents = query.list();

        return storedEvents;
	}

	@Override
	public List<StoredEvent> allStoredEventsSince(long aStoredEventId) {
		Query query =
                this.session().createQuery(
                        "from StoredEvent as _obj_ "
                        + "where _obj_.eventId > ? "
                        + "order by _obj_.eventId");

        query.setParameter(0, aStoredEventId);

        List<StoredEvent> storedEvents = query.list();

        return storedEvents;
	}

	@Override
	public StoredEvent append(DomainEvent aDomainEvent) {
		String eventSerialization =
                EventSerializer.instance().serialize(aDomainEvent);

        StoredEvent storedEvent =
                new StoredEvent(
                        aDomainEvent.getClass().getName(),
                        aDomainEvent.occurredOn(),
                        eventSerialization);

        this.session().save(storedEvent);

        return storedEvent;
	}

	@Override
	public void close() {
		

	}

	@Override
	public long countStoredEvents() {
		Query query =
                this.session().createQuery("select count(*) from StoredEvent");

        long count = ((Long) query.uniqueResult()).longValue();

        return count;
	}

}
